package top.zhouze.common.base;

import android.util.Log;
import androidx.room.*;
import androidx.sqlite.db.SimpleSQLiteQuery;
import androidx.sqlite.db.SupportSQLiteQuery;
import top.zhouze.common.annotation.TableName;
import io.reactivex.Single;
import top.zhouze.common.util.ReflectUtil;
import top.zhouze.common.util.StrUtil;

import java.lang.reflect.ParameterizedType;
import java.util.List;
import java.util.Objects;

/**
 * @author 周仄
 * @since 2023/11/13 13:41
 */
public abstract class BaseDao<T> {
    private String tableName;

    @Insert
    public abstract Single<List<Long>> insert(List<T> entities);

    @Insert
    public abstract Single<List<Long>> insert(T... entities);

    @Delete
    public abstract Single<Integer> delete(T... entities);

    @Delete
    public abstract Single<Integer> delete(List<T> entities);

    @Update
    public abstract Single<Integer> update(T... entities);

    @Update
    public abstract Single<Integer> update(List<T> entities);

    public Single<Integer> count() {
        SimpleSQLiteQuery query = new SimpleSQLiteQuery(
                "select count(1) from " + getTableName()
        );
        Log.d("sql", query.getSql());
        return execute(query);
    }

    public Single<Integer> deleteAll() {
        SimpleSQLiteQuery query = new SimpleSQLiteQuery(
                "delete from " + getTableName()
        );
        Log.d("sql", query.getSql());
        return execute(query);
    }

    public Single<Integer> deleteById(long id) {
        SimpleSQLiteQuery query = new SimpleSQLiteQuery(
                "delete from ? where id = ?", new String[]{getTableName(), String.valueOf(id)}
        );
        Log.d("sql", query.getSql());
        return execute(query);
    }

    public Single<List<T>> findAll() {
        SimpleSQLiteQuery query = new SimpleSQLiteQuery(
                "select * from " + getTableName()
        );
        Log.d("sql",query.getSql());
        return doFindAll(query);
    }

    public Single<T> find(long id) {
        SimpleSQLiteQuery query = new SimpleSQLiteQuery(
                "select * from ? where id = ?" + id, new String[]{getTableName(), String.valueOf(id)}
        );
        Log.d("sql",query.getSql());
        return doFind(query);
    }

    private String getTableName() {
        if (tableName == null) {
            Class<?> cls = ReflectUtil.getGenericClass((Class<?>) Objects.requireNonNull(getClass().getGenericSuperclass()),0);
            TableName entity = cls.getAnnotation(TableName.class);
            if (entity != null) {
                tableName = entity.value();
            }
            if (tableName == null || "".equals(tableName)) {
                tableName = StrUtil.humpToUnderline(cls.getSimpleName());
            }
        }
        return tableName;
    }

    @RawQuery
    protected abstract Single<List<T>> doFindAll(SupportSQLiteQuery query);

    @RawQuery
    protected abstract Single<T> doFind(SupportSQLiteQuery query);

    @RawQuery
    protected abstract Single<Integer> execute(SupportSQLiteQuery query);

}
